let idCounter = 0;

function uniqueId(prefix = "") {
  return `${prefix}${++idCounter}`;
}

function reduce(collection, iteratee, accumulator) {
  let result = accumulator !== undefined ? accumulator : collection[0];
  const startIndex = accumulator !== undefined ? 0 : 1;

  for (let i = startIndex; i < collection.length; i++) {
    result = iteratee(result, collection[i], i, collection);
  }

  return result;
}

function debounce(func, wait) {
  let timeout = null;

  return function (...args) {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}
function findIndex(array, predicate) {
  for (let i = 0; i < array.length; i++) {
    if (predicate(array[i], i, array)) {
      return i;
    }
  }
  return -1;
}

function cloneDeep(obj,hash = new WeakMap()) {
    // 如果是基本类型或 null，直接返回
     if (obj === null || typeof obj !== 'object') {
       return obj;
     }
   
     // 如果是 Date 类型，返回新的 Date 对象
     if (obj instanceof Date) {
       return new Date(obj);
     }
   
     // 如果是 RegExp 类型，返回新的 RegExp 对象
     if (obj instanceof RegExp) {
       return new RegExp(obj);
     }
   
     // 如果已经拷贝过该对象，直接返回
     if (hash.has(obj)) {
       return hash.get(obj);
     }
   
     // 创建新对象或数组
     const cloneObj = Array.isArray(obj) ? [] : {};
   
     // 将当前对象存入哈希表，避免循环引用
     hash.set(obj, cloneObj);
   
     // 递归拷贝属性
     for (let key in obj) {
       if (obj.hasOwnProperty(key)) {
         cloneObj[key] = cloneDeep(obj[key], hash);
       }
     }
   
     return cloneObj;
}

function uniqWith(array, comparator) {
  return array.filter((item, index, self) => {
    return self.findIndex((other) => comparator(item, other)) === index;
  });
}

function isEqual(value, other) {
  if (value === other) return true; // 基本类型直接比较

  if (
    typeof value !== "object" ||
    typeof other !== "object" ||
    value === null ||
    other === null
  ) {
    return false; // 非对象类型不相等
  }

  const keys1 = Object.keys(value);
  const keys2 = Object.keys(other);

  if (keys1.length !== keys2.length) return false; // 键数量不同

  for (const key of keys1) {
    if (!keys2.includes(key) || !isEqual(value[key], other[key])) {
      return false; // 键或值不相等
    }
  }

  return true;
}

function floor(number, precision = 0) {
  const factor = Math.pow(10, precision);
  return Math.floor(number * factor) / factor;
}

function clamp(number, lower, upper) {
  return Math.min(Math.max(number, lower), upper);
}

function add(a, b) {
  return a + b;
}

function max(array) {
  if (!array || array.length === 0) return undefined;
  return Math.max(...array);
}

function ceil(number, precision = 0) {
  const factor = Math.pow(10, precision);
  return Math.ceil(number * factor) / factor;
}

function round(number, precision = 0) {
  const factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}

export const _ = {
  uniqueId,
  round,
  ceil,
  max,
  add,
  clamp,
  floor,
  isEqual,
  uniqWith,
  cloneDeep,
  findIndex,
  debounce,
  reduce,
};
